/*
 * Copyright (c) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved.
 *
 * UniProton is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * Create: 2024-01-14
 * Description: sbi 接口
 */

#include "sbi.h"

#define SBI_EMBED __asm__ __volatile__

#define __sbi_param(exten_id, func_id)  SBI_EMBED("add a7, %0, zero"::"r"((exten_id)):"a0","a1","a2","a3","a4","a5");SBI_EMBED("add a6, %0, zero"::"r"((func_id)):"a0","a1","a2","a3","a4","a5");

#define __sbi_param_ret() SBI_EMBED("add %0, a0, zero":"=r"(ret.error)::);SBI_EMBED("add %0, a1, zero":"=r"(ret.value)::);

#define __sbi_call() __asm__ __volatile__("ecall");



sbi_ret_t sbi_hart_start(unsigned  long  hartid, unsigned long start_addr, unsigned long opaque)
{
    // 所在扩展              :  HSM 扩展 -> EID_HSM
    // 功能号为              :  0号功能号 -> FID_HSM_SBI_HART_START
    // 根据sbi2.0 手册建议，使用unsigned long long 来存放扩展ID 和功能ID
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_HSM;
    func_id  = FID_HSM_SBI_HART_START;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_hart_stop(void)
{
    // 所在扩展              :  HSM 扩展 -> EID_HSM
    // 功能号为              :  1号功能号 -> FID_HSM_SBI_HART_STOP
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_HSM;
    func_id  = FID_HSM_SBI_HART_STOP;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_hart_get_status(unsigned long hartid)
{
    // 所在扩展              :  HSM 扩展 -> EID_HSM
    // 功能号为              :  2号功能号 ->FID_SBI_HART_GET_STATUS 
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_HSM;
    func_id  = FID_SBI_HART_GET_STATUS;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_hart_suspend(uint32_t suspend_type, unsigned long resume_addr, unsigned long opaque)
{
    // 所在扩展              :  HSM 扩展 -> EID_HSM
    // 功能号为              :  3号功能号 ->FID_SBI_HART_SUSPEND 
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_HSM;
    func_id  = FID_SBI_HART_SUSPEND;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_get_spec_version()
{
    // 所在扩展              :  BASE 扩展 -> EID_BASE
    // 功能号为              :  0号功能号 -> FID_BASE_GET_SBI_VERSION
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_BASE;
    func_id  = FID_BASE_GET_SBI_VERSION;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}

sbi_ret_t sbi_get_impl_id()
{
    // 所在扩展              :  BASE 扩展 -> EID_BASE
    // 功能号为              :  1号功能号 -> FID_BASE_GET_SBI_IMPL_ID
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_BASE;
    func_id  = FID_BASE_GET_SBI_IMPL_ID;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}

sbi_ret_t sbi_get_impl_version()
{
    // 所在扩展              :  BASE 扩展 -> EID_BASE
    // 功能号为              :  2号功能号 -> FID_BASE_GET_SBI_IMPL_VER
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_BASE;
    func_id  = FID_BASE_GET_SBI_IMPL_VER;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}

sbi_ret_t sbi_probe_extension(long extension_id)
{
    // 所在扩展              :   BASE 扩展 -> EID_BASE
    // 功能号为              :   3号功能号 -> FID_BASE_PROBE_SBI_EXTEN
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_BASE;
    func_id  = FID_BASE_PROBE_SBI_EXTEN;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}

sbi_ret_t sbi_get_mvendorid()
{
    // 所在扩展              :   BASE 扩展 -> EID_BASE
    // 功能号为              :   4号功能号 -> FID_BASE_GET_MHART_ID
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_BASE;
    func_id  = FID_BASE_GET_MHART_ID;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_get_marchid()
{
    // 所在扩展              :   BASE 扩展 -> EID_BASE
    // 功能号为              :   5号功能号 -> FID_BASE_GET_MARCHID
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_BASE;
    func_id  = FID_BASE_GET_MARCHID;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}

sbi_ret_t sbi_get_mimpid()
{
    // 所在扩展              :   BASE 扩展 -> EID_BASE
    // 功能号为              :   6号功能号 -> FID_BASE_GET_MIMPID
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_BASE;
    func_id  = FID_BASE_GET_MIMPID;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_debug_console_write(unsigned long num_bytes,   unsigned long base_addr_lo,   unsigned long base_addr_hi)
{
    // 所在扩展              :   BASE 扩展 -> EID_DEBUG
    // 功能号为              :   0号功能号 -> FID_DEBUG_CONSOLE_WRITE
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_DEBUG;
    func_id  = FID_DEBUG_CONSOLE_WRITE;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_debug_console_read(unsigned long num_bytes,   unsigned long base_addr_lo,   unsigned long base_addr_hi)
{
    // 所在扩展              :   DEBUG 扩展 -> EID_DEBUG
    // 功能号为              :   1号功能号 -> FID_DEBUG_CONSOLE_READ
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_DEBUG;
    func_id  = FID_DEBUG_CONSOLE_READ;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_debug_console_write_byte(uint8_t byte)
{
    // 所在扩展              :   DEBUG 扩展 -> EID_DEBUG
    // 功能号为              :   2号功能号 -> FID_DEBUG_CONSOLE_WRITE_BYTE
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_DEBUG;
    func_id  = FID_DEBUG_CONSOLE_WRITE_BYTE;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}


sbi_ret_t sbi_system_suspend(uint32_t sleep_type,   unsigned long resume_addr,   unsigned long opaque)
{
    // 所在扩展              :   HANG 扩展 -> EID_HANG
    // 功能号为              :   0号功能号 -> FID_HANG_SBI_SYSTEM_SUSPEND
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_HANG;
    func_id  = FID_HANG_SBI_SYSTEM_SUSPEND;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}



sbi_ret_t sbi_set_timer(uint64_t stime_value)
{
    // 所在扩展              :   TIME 扩展 -> EID_TIME
    // 功能号为              :   0号功能号 -> FID_TIME_SET_TIMER
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_TIME;
    func_id  = FID_TIME_SET_TIMER;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}



sbi_ret_t sbi_send_ipi(unsigned long hart_mask,unsigned long hart_mask_base)
{
    // 所在扩展              :   IPI 扩展 -> EID_IPI
    // 功能号为              :   0号功能号 -> FID_IPI_SEND_IPI
    sbi_ret_t ret;
    unsigned long long exten_id;
    unsigned long long func_id;
    exten_id = EID_IPI;
    func_id  = FID_IPI_SEND_IPI;
    __sbi_param(exten_id,func_id);
    __sbi_call();
    __sbi_param_ret();
    return ret;
}













